﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Transactions;
using System.Windows.Forms;
using PayexpDAL;
using Utilities;
using System.Globalization;
using ExcelHandler;
using PayexpUserControls;
using PresentationControls;

namespace Moneymatters
{
    public partial class MainForm
    {
        #region Private Fields

        private TransactionType chosenParentTransactionTypeForAddingChildren;
        private TransactionTypeTreeViewForm _formForSelectingIncomeHeadsForSettingDefaultValues;
        private TransactionTypeTreeViewForm _formForSelectingExpenseHeadsForSettingDefaultValues;
        private TransactionTypeTreeViewForm _formForSelectingParentForAddingChildren;
        private bool _loadComboBoxesForDefaultValuesSetting = true;
        
        #endregion Private Fields

        #region Properties
        #endregion Properties

        #region Private Methods

        #region Existing Defaults
        private void PopulateExistingDefaultValuesTreeView()
        {
            List<HeadDefaultValue> existingDefaultValueList = this.dataAccessHandlerCommonInstance.GetAllHeadDefaultValues(MainForm.Context);
            if (existingDefaultValueList.Count == 0)
            {
                labelAvailableDefaults.Text = "Available Defaults (" + existingDefaultValueList.Count.ToString() + ")";
                return;
            }

            List<TransactionType> transactionTypeListToBuildTree = GetDistinctTransactionTypeList(existingDefaultValueList);
            List<TransactionType> orderedTransactionTypeListToBuildTree = ArrangeItems(transactionTypeListToBuildTree);

            List<TransactionType> clonedListToBuildTree = new List<TransactionType>();
            foreach (TransactionType transactionType in orderedTransactionTypeListToBuildTree)
            {
                TransactionType clone = new TransactionType();
                clone.Id = transactionType.Id;
                clone.ParentId = transactionType.ParentId;
                clone.Name = transactionType.Name;
                clonedListToBuildTree.Add(clone);
            }

            Random random = new Random();
            foreach (HeadDefaultValue existingDefaultValue in existingDefaultValueList)
            {
                TransactionType clonedLeafNode = clonedListToBuildTree.Where(t => t.Id.Equals(existingDefaultValue.TransactionTypeId)).FirstOrDefault();
                if (clonedLeafNode != null)
                {
                    if (existingDefaultValue.Amount.HasValue)
                    {
                        TransactionType defaultAmount = new TransactionType();
                        defaultAmount.Id = random.Next();
                        defaultAmount.ParentId = clonedLeafNode.Id;
                        defaultAmount.Name = "Amount: " + existingDefaultValue.Amount.ToString();
                        clonedListToBuildTree.Add(defaultAmount);
                    }

                    if (!string.IsNullOrEmpty(existingDefaultValue.TransactionModeValue))
                    {
                        TransactionType defaultTransactionModeValue = new TransactionType();
                        defaultTransactionModeValue.Id = random.Next();
                        defaultTransactionModeValue.ParentId = clonedLeafNode.Id;

                        StaticList staticList = SettingsAndStaticListLoader.TransactionModeList.Where(t => t.ListItemCode.Equals(existingDefaultValue.TransactionModeValue)).FirstOrDefault();
                        if (staticList != null)
                        {
                            defaultTransactionModeValue.Name = "Transaction Mode: " + staticList.ListItemValue;
                            clonedListToBuildTree.Add(defaultTransactionModeValue);
                        }
                    }

                    if (!string.IsNullOrEmpty(existingDefaultValue.BankName))
                    {
                        TransactionType defaultBank = new TransactionType();
                        defaultBank.Id = random.Next();
                        defaultBank.ParentId = clonedLeafNode.Id;

                        StaticList staticList = SettingsAndStaticListLoader.BankAccountsStaticList.Where(t => t.ListItemCode.Equals(existingDefaultValue.BankName)).FirstOrDefault();
                        if (staticList != null)
                        {
                            defaultBank.Name = "Bank Account: " + staticList.ListItemValue;
                            clonedListToBuildTree.Add(defaultBank);
                        }
                    }

                    if (!string.IsNullOrEmpty(existingDefaultValue.Narration))
                    {
                        TransactionType defaultNarration = new TransactionType();
                        defaultNarration.Id = random.Next();
                        defaultNarration.ParentId = clonedLeafNode.Id;
                        defaultNarration.Name = "Narration: " + existingDefaultValue.Narration;
                        clonedListToBuildTree.Add(defaultNarration);
                    }

                    if (!string.IsNullOrEmpty(existingDefaultValue.ExpenseApproverIdList))
                    {
                        TransactionType defaultApprovers = new TransactionType();
                        defaultApprovers.Id = random.Next();
                        defaultApprovers.ParentId = clonedLeafNode.Id;

                        List<int> approverIdList = existingDefaultValue.ExpenseApproverIdList.GetIntegerListFromSquareBracketedCommaSeparatedString();
                        List<ExpenseApprover> requiredList = SettingsAndStaticListLoader.ExpenseApproverList.Where(t => approverIdList.Contains(t.Id)).ToList();
                        string text = string.Join(", ", requiredList.Select(t => t.FirstName).ToList());

                        defaultApprovers.Name = "Approval: " + text;
                        clonedListToBuildTree.Add(defaultApprovers);
                    }

                    if (existingDefaultValue.IsAutoApproved.HasValue)
                    {
                        TransactionType defaultAutoApproval = new TransactionType();
                        defaultAutoApproval.Id = random.Next();
                        defaultAutoApproval.ParentId = clonedLeafNode.Id;

                        defaultAutoApproval.Name = "Approval: Auto Approved";
                        clonedListToBuildTree.Add(defaultAutoApproval);
                    }
                }
            }

            List<TransactionType> clonedOrderedListToBuildTree = ArrangeItems(clonedListToBuildTree);
            this.treeViewExistingHeadDefaultValues.Nodes.Clear();
            CreateTreeView(clonedOrderedListToBuildTree, this.treeViewExistingHeadDefaultValues);
            labelAvailableDefaults.Text = "Available Defaults (" + existingDefaultValueList.Count.ToString() + ")";
            //rootHeadToApproverMappingTreeNode.Nodes.Clear();
            //setForAutoApprovalTreeNode.Nodes.Clear();
            //byConfigureHeadTreeNode.Nodes.Clear();
            //byApproverTreeNode.Nodes.Clear();

            //rootHeadToApproverMappingTreeNode.Nodes.Add(byConfigureHeadTreeNode);
            //rootHeadToApproverMappingTreeNode.Nodes.Add(byApproverTreeNode);
            //rootHeadToApproverMappingTreeNode.Nodes.Add(setForAutoApprovalTreeNode);
            //this.treeViewExistingHeadsToApproverMapping.Nodes.Clear();
            //this.treeViewExistingHeadsToApproverMapping.Nodes.Add(rootHeadToApproverMappingTreeNode);

            //List<TransactionType> distinctTransactionTypeList = GetDistincTransactionTypeList(existingMapping);
            //List<ExpenseApprover> distinctExpenseApproverList = GetDistinctExpenseApproverList(existingMapping);

            //PopulateAutoApprovalTree(existingMapping, distinctTransactionTypeList, distinctExpenseApproverList);
            //PopulateByHeadTree(existingMapping, distinctTransactionTypeList, distinctExpenseApproverList);
            //PopulateByApproverTree(existingMapping, distinctTransactionTypeList, distinctExpenseApproverList);
            //this.treeViewExistingHeadsToApproverMapping.ExpandAll();
        }

        private List<TransactionType> GetDistinctTransactionTypeList(List<HeadDefaultValue> existingDefaultValueList)
        {
            List<int> allNodeIdList = new List<int>();
            // first all the leaf node id
            allNodeIdList.AddRange(existingDefaultValueList.Select(t => t.TransactionTypeId).ToList());

            // get all the hierarchy id added
            foreach (var mapping in existingDefaultValueList)
            {
                allNodeIdList.AddRange(mapping.HierarchyIdList.GetIntegerListFromSquareBracketedCommaSeparatedString());
            }

            // remove duplicates and get distinct list
            List<int> distinctNodeIdList = allNodeIdList.Distinct().ToList();
            List<TransactionType> distinctTransactionTypeList = this.dataAccessHandlerCommonInstance.GetTransactionTypeListByIdList(distinctNodeIdList, MainForm.Context);

            return distinctTransactionTypeList;
        }
        #endregion Existing Defaults

        #region Populate 
        private void PopulateComboBoxesForDefaultValueSelection()
        {
            if (this._loadComboBoxesForDefaultValuesSetting)
            {
                // expense 
                List<ExpenseApprover> temp = new List<ExpenseApprover>();
                temp.AddRange(SettingsAndStaticListLoader.ExpenseApproverList);
                ListSelectionWrapper<ExpenseApprover> expenseApproverList = new ListSelectionWrapper<ExpenseApprover>(temp, "DisplayName");
                this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.DataSource = expenseApproverList;
                this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.DisplayMemberSingleItem = "Name";
                this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.DisplayMember = "NameConcatenated";
                this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.ValueMember = "Selected";

                foreach (StaticList staticList in SettingsAndStaticListLoader.BankAccountsStaticList)
                {
                    ComboBoxItem comboBoxItem = new ComboBoxItem(staticList.ListItemValue, staticList);
                    this.comboBoxExpenseHeadDefaultBankAccount.Items.Add(comboBoxItem);
                }

                foreach (StaticList staticList in SettingsAndStaticListLoader.TransactionModeList.Where(t => !t.ListItemCode.Equals("transaction_mode_bankcredit")))
                {
                    ComboBoxItem comboBoxItem = new ComboBoxItem(staticList.ListItemValue, staticList);
                    this.comboBoxExpenseHeadDefaultTransactionMode.Items.Add(comboBoxItem);
                }

                // all disabled the first time
                this.radioButtonSetExpenseHeadApprovers.Enabled = false;
                this.radioButtonSetExpenseHeadAutoApproval.Enabled = false;
                this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.Enabled = false;
                this.textBoxExpenseHeadDefaultAmount.Enabled = false;
                this.textBoxExpenseHeadDefaultNarration.Enabled = false;
                this.comboBoxExpenseHeadDefaultTransactionMode.Enabled = false;
                this.comboBoxExpenseHeadDefaultBankAccount.Enabled = false;
               

                // income 
                foreach (StaticList staticList in SettingsAndStaticListLoader.BankAccountsStaticList)
                {
                    ComboBoxItem comboBoxItem = new ComboBoxItem(staticList.ListItemValue, staticList);
                    this.comboBoxIncomeHeadDefaultBankAccount.Items.Add(comboBoxItem);
                }

                foreach (StaticList staticList in SettingsAndStaticListLoader.TransactionModeList.Where(t => !t.ListItemCode.Equals("transaction_mode_bankdebit") &&
                                                                                     !t.ListItemCode.Equals("transaction_mode_pettycashwithdrawal")))
                {
                    ComboBoxItem comboBoxItem = new ComboBoxItem(staticList.ListItemValue, staticList);
                    this.comboBoxIncomeHeadDefaultTransactionMode.Items.Add(comboBoxItem);
                }

                // all disabled the first time
                this.textBoxIncomeHeadDefaultAmount.Enabled = false;
                this.textBoxIncomeHeadDefaultNarration.Enabled = false;
                this.comboBoxIncomeHeadDefaultTransactionMode.Enabled = false;
                this.comboBoxIncomeHeadDefaultBankAccount.Enabled = false;

                this._loadComboBoxesForDefaultValuesSetting = false;
            }
        }

        private void PopulateIncomeHeadSelectionForDefaultValuesTreeView()
        {
            _formForSelectingIncomeHeadsForSettingDefaultValues = new TransactionTypeTreeViewForm(false, true, true);
            this.treeViewSelectIncomeHeadsForSettingDefaultValues.Nodes.Clear();
            this.treeViewSelectIncomeHeadsForSettingDefaultValues.CheckBoxes = true;
            _formForSelectingIncomeHeadsForSettingDefaultValues.UseExternalTreeView(ref this.treeViewSelectIncomeHeadsForSettingDefaultValues);
            _formForSelectingIncomeHeadsForSettingDefaultValues.CreateTreeView(new List<string>(), true, false);
            this.treeViewSelectIncomeHeadsForSettingDefaultValues.Refresh();
            this.treeViewSelectIncomeHeadsForSettingDefaultValues.Visible = true;
        }

        private void PopulateExpenseHeadSelectionForDefaultValuesTreeView()
        {
            _formForSelectingExpenseHeadsForSettingDefaultValues = new TransactionTypeTreeViewForm(false, true, true);
            this.treeViewSelectExpenseHeadsForSettingDefaultValues.Nodes.Clear();
            this.treeViewSelectExpenseHeadsForSettingDefaultValues.CheckBoxes = true;
            _formForSelectingExpenseHeadsForSettingDefaultValues.UseExternalTreeView(ref this.treeViewSelectExpenseHeadsForSettingDefaultValues);
            _formForSelectingExpenseHeadsForSettingDefaultValues.CreateTreeView(new List<string>(), false, true);
            this.treeViewSelectExpenseHeadsForSettingDefaultValues.Refresh();
            this.treeViewSelectExpenseHeadsForSettingDefaultValues.Visible = true;
        }
        #endregion Populate

        #region Income Head Default Values

        private void buttonRefreshIncomeHeadSelectionTreeView_Click(object sender, EventArgs e)
        {
            PopulateIncomeHeadSelectionForDefaultValuesTreeView();
        }

        private void buttonSaveIncomeHeadDefaultValues_Click(object sender, EventArgs e)
        {
            List<TransactionType> checkedLeafNodeList = this._formForSelectingIncomeHeadsForSettingDefaultValues.GetCheckedLeafNodes();
            if (checkedLeafNodeList.Count == 0)
            {
                MessageBox.Show("Please choose at least one leaf node to configure", "Choose a leaf node", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (!checkBoxExpenseHeadDefaultApprovers.Checked &&
                !checkBoxIncomeHeadDefaultAmount.Checked &&
                !checkBoxIncomeHeadDefaultNarration.Checked &&
                !checkBoxIncomeHeadDefaultTransactionMode.Checked &&
                !checkBoxIncomeHeadDefaultBankAccount.Checked)
            {
                MessageBox.Show("Please set one or more default values for the selected leaf heads.", "Set default values", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            try
            {
                List<string> errorMessages = new List<string>();
                HeadDefaultValue headDefaultValue = new HeadDefaultValue();
                if (checkBoxExpenseHeadDefaultApprovers.Checked)
                {
                    if (this.radioButtonSetExpenseHeadApprovers.Checked)
                    {
                        ListSelectionWrapper<ExpenseApprover> dataSource = (ListSelectionWrapper<ExpenseApprover>)this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.DataSource;

                        if (!dataSource.Any(t => t.Selected))
                        {
                            errorMessages.Add("Please choose at least one approver to configure Or choose 'Auto Approval'.");
                        }
                        else
                        {
                            List<ExpenseApprover> selectedApproverList = new List<ExpenseApprover>();
                            foreach (var item in dataSource.Where(t => t.Selected))
                            {
                                selectedApproverList.Add(item.Item);
                            }

                            headDefaultValue.ExpenseApproverIdList = selectedApproverList.Select(t => t.Id).ToList().GetSquareBracketedCommaSeparatedString();
                        }
                    }
                    else
                    {
                        headDefaultValue.IsAutoApproved = true;
                    }
                }
                
                if (checkBoxIncomeHeadDefaultAmount.Checked)
                {
                    string amount = this.textBoxIncomeHeadDefaultAmount.Text.Trim();
                    decimal amountValue;
                    if (amount.ValidateAmountValue(2, out amountValue))
                    {
                        headDefaultValue.Amount = amountValue;
                    }
                    else
                    {
                        errorMessages.Add("Please enter a valid value in the amount field. All amount values should be non-negative and can have only 2 digits after the decimal.");
                    }

                }

                if (checkBoxIncomeHeadDefaultNarration.Checked)
                {
                    if (string.IsNullOrEmpty(this.textBoxIncomeHeadDefaultNarration.Text.Trim()))
                    {
                        errorMessages.Add("Please enter a valid value for default narration.");
                    }
                    else
                    {
                        headDefaultValue.Narration = this.textBoxIncomeHeadDefaultNarration.Text.Trim();
                    }
                }

                if (checkBoxIncomeHeadDefaultTransactionMode.Checked)
                {
                    headDefaultValue.TransactionModeValue = ((StaticList)((ComboBoxItem)this.comboBoxIncomeHeadDefaultTransactionMode.SelectedItem).Value).ListItemCode;
                }

                if (checkBoxIncomeHeadDefaultBankAccount.Checked)
                {
                    headDefaultValue.BankName = ((StaticList)((ComboBoxItem)this.comboBoxIncomeHeadDefaultBankAccount.SelectedItem).Value).ListItemCode;
                }

                if (errorMessages.Count > 0)
                {
                    MessageBox.Show(string.Join(Environment.NewLine, errorMessages.ToArray()), "Save successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    headDefaultValue.CreatedBy = LoginForm.LoggedInUserName;
                    headDefaultValue.CreatedDate = DateTime.Now;
                    headDefaultValue.UpdatedBy = LoginForm.LoggedInUserName;
                    headDefaultValue.UpdatedDate = DateTime.Now;
                    headDefaultValue.IsActive = true;


                    this.dataAccessHandlerCommonInstance.InsertOrUpdateHeadDefaultValues(checkedLeafNodeList, headDefaultValue, MainForm.Context);
                    MessageBox.Show("Default values saved successfully.", "Save successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    ResetIncomeHeadDefaultValuesControls();
                    this._formForSelectingIncomeHeadsForSettingDefaultValues.CheckAllChildNodes(this.treeViewSelectIncomeHeadsForSettingDefaultValues.Nodes[0], false);
                    
                    
                    PopulateExistingDefaultValuesTreeView();
                }
            }
            catch
            {
                MessageBox.Show("Sorry, there was an error trying to save the default values. Please try again or contact your administrator.", "Error saving configuration", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void checkBoxIncomeHeadDefaultAmount_CheckedChanged(object sender, EventArgs e)
        {
            this.textBoxIncomeHeadDefaultAmount.Enabled = this.checkBoxIncomeHeadDefaultAmount.Checked;
        }

        private void checkBoxIncomeHeadDefaultNarration_CheckedChanged(object sender, EventArgs e)
        {
            this.textBoxIncomeHeadDefaultNarration.Enabled = this.checkBoxIncomeHeadDefaultNarration.Checked;
        }

        private void checkBoxIncomeHeadDefaultTransactionMode_CheckedChanged(object sender, EventArgs e)
        {
            this.comboBoxIncomeHeadDefaultTransactionMode.Enabled = this.checkBoxIncomeHeadDefaultTransactionMode.Checked;
        }

        private void checkBoxIncomeHeadDefaultBankAccount_CheckedChanged(object sender, EventArgs e)
        {
            this.comboBoxIncomeHeadDefaultBankAccount.Enabled = this.checkBoxIncomeHeadDefaultBankAccount.Checked;
        }

        private void ResetIncomeHeadDefaultValuesControls()
        {
            this.checkBoxIncomeHeadDefaultAmount.Checked = false;
            this.textBoxIncomeHeadDefaultAmount.Enabled = this.checkBoxIncomeHeadDefaultAmount.Checked;
            this.textBoxIncomeHeadDefaultAmount.Clear();

            this.checkBoxIncomeHeadDefaultNarration.Checked = false;
            this.textBoxIncomeHeadDefaultNarration.Enabled = this.checkBoxIncomeHeadDefaultNarration.Checked;
            this.textBoxIncomeHeadDefaultNarration.Clear();

            this.checkBoxIncomeHeadDefaultTransactionMode.Checked = false;
            this.comboBoxIncomeHeadDefaultTransactionMode.Enabled = this.checkBoxIncomeHeadDefaultTransactionMode.Checked;

            this.checkBoxIncomeHeadDefaultBankAccount.Checked = false;
            this.comboBoxIncomeHeadDefaultBankAccount.Enabled = this.checkBoxIncomeHeadDefaultBankAccount.Checked;
        }
        
        #endregion Income Head Default Values

        #region Expense Head Default Values

        private void buttonRefreshExpenseHeadSelectionTreeViews_Click(object sender, EventArgs e)
        {
            PopulateExpenseHeadSelectionForDefaultValuesTreeView();
        }

        private void buttonSaveExpenseHeadDefaultValues_Click(object sender, EventArgs e)
        {
            List<TransactionType> checkedLeafNodeList = this._formForSelectingExpenseHeadsForSettingDefaultValues.GetCheckedLeafNodes();
            if (checkedLeafNodeList.Count == 0)
            {
                MessageBox.Show("Please choose at least one leaf node to configure", "Choose a leaf node", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            if (!checkBoxExpenseHeadDefaultApprovers.Checked &&
                !checkBoxExpenseHeadDefaultAmount.Checked &&
                !checkBoxExpenseHeadDefaultNarration.Checked &&
                !checkBoxExpenseHeadDefaultTransactionMode.Checked &&
                !checkBoxExpenseHeadDefaultBankAccount.Checked)
            {
                MessageBox.Show("Please set one or more default values for the selected leaf heads.", "Set default values", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            try
            {
                List<string> errorMessages = new List<string>();
                HeadDefaultValue headDefaultValue = new HeadDefaultValue();
                if (checkBoxExpenseHeadDefaultApprovers.Checked)
                {
                    if (this.radioButtonSetExpenseHeadApprovers.Checked)
                    {
                        ListSelectionWrapper<ExpenseApprover> dataSource = (ListSelectionWrapper<ExpenseApprover>)this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.DataSource;

                        if (!dataSource.Any(t => t.Selected))
                        {
                            errorMessages.Add("Please choose at least one approver to configure Or choose 'Auto Approval'.");
                        }
                        else
                        {
                            List<ExpenseApprover> selectedApproverList = new List<ExpenseApprover>();
                            foreach (var item in dataSource.Where(t => t.Selected))
                            {
                                selectedApproverList.Add(item.Item);
                            }

                            headDefaultValue.ExpenseApproverIdList = selectedApproverList.Select(t => t.Id).ToList().GetSquareBracketedCommaSeparatedString();
                        }
                    }
                    else
                    {
                        headDefaultValue.IsAutoApproved = true;
                    }
                }

                if (checkBoxExpenseHeadDefaultAmount.Checked)
                {
                    string amount = this.textBoxExpenseHeadDefaultAmount.Text.Trim();
                    decimal amountValue;
                    if (amount.ValidateAmountValue(2, out amountValue))
                    {
                        headDefaultValue.Amount = amountValue;
                    }
                    else
                    {
                        errorMessages.Add("Please enter a valid value in the amount field. All amount values should be non-negative and can have only 2 digits after the decimal.");
                    }

                }

                if (checkBoxExpenseHeadDefaultNarration.Checked)
                {
                    if (string.IsNullOrEmpty(this.textBoxExpenseHeadDefaultNarration.Text.Trim()))
                    {
                        errorMessages.Add("Please enter a valid value for default narration.");
                    }
                    else
                    {
                        headDefaultValue.Narration = this.textBoxExpenseHeadDefaultNarration.Text.Trim();
                    }
                }

                if (checkBoxExpenseHeadDefaultTransactionMode.Checked)
                {
                    headDefaultValue.TransactionModeValue = ((StaticList)((ComboBoxItem)this.comboBoxExpenseHeadDefaultTransactionMode.SelectedItem).Value).ListItemCode;
                }

                if (checkBoxExpenseHeadDefaultBankAccount.Checked)
                {
                    headDefaultValue.BankName = ((StaticList)((ComboBoxItem)this.comboBoxExpenseHeadDefaultBankAccount.SelectedItem).Value).ListItemCode;
                }

                if (errorMessages.Count > 0)
                {
                    MessageBox.Show(string.Join(Environment.NewLine, errorMessages.ToArray()), "Save successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    headDefaultValue.CreatedBy = LoginForm.LoggedInUserName;
                    headDefaultValue.CreatedDate = DateTime.Now;
                    headDefaultValue.UpdatedBy = LoginForm.LoggedInUserName;
                    headDefaultValue.UpdatedDate = DateTime.Now;
                    headDefaultValue.IsActive = true;


                    this.dataAccessHandlerCommonInstance.InsertOrUpdateHeadDefaultValues(checkedLeafNodeList, headDefaultValue, MainForm.Context);
                    MessageBox.Show("Default values saved successfully.", "Save successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    ResetExpenseHeadDefaultValuesControls();
                    this._formForSelectingExpenseHeadsForSettingDefaultValues.CheckAllChildNodes(this.treeViewSelectExpenseHeadsForSettingDefaultValues.Nodes[0], false);
                    this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.ClearSelection();
                    PopulateExistingDefaultValuesTreeView();
                }
            }
            catch
            {
                MessageBox.Show("Sorry, there was an error trying to save the default values. Please try again or contact your administrator.", "Error saving configuration", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

       

        private void radioButtonSetExpenseHeadApprovers_CheckedChanged(object sender, EventArgs e)
        {
            this.radioButtonSetExpenseHeadAutoApproval.Checked = !this.radioButtonSetExpenseHeadApprovers.Checked;
            this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.Enabled = this.radioButtonSetExpenseHeadApprovers.Checked;
        }

        private void radioButtonSetExpenseHeadAutoApproval_CheckedChanged(object sender, EventArgs e)
        {
            this.radioButtonSetExpenseHeadApprovers.Checked = !this.radioButtonSetExpenseHeadAutoApproval.Checked;
            this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.Enabled = this.radioButtonSetExpenseHeadApprovers.Checked;
        }

        private void checkBoxExpenseHeadDefaultApprovers_CheckedChanged(object sender, EventArgs e)
        {
            this.radioButtonSetExpenseHeadApprovers.Enabled = this.checkBoxExpenseHeadDefaultApprovers.Checked;
            this.radioButtonSetExpenseHeadAutoApproval.Enabled = this.checkBoxExpenseHeadDefaultApprovers.Checked;
            this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.Enabled = !this.radioButtonSetExpenseHeadAutoApproval.Checked;
        }

        private void checkBoxExpenseHeadDefaultAmount_CheckedChanged(object sender, EventArgs e)
        {
            this.textBoxExpenseHeadDefaultAmount.Enabled = this.checkBoxExpenseHeadDefaultAmount.Checked;
        }

        private void checkBoxExpenseHeadDefaultNarration_CheckedChanged(object sender, EventArgs e)
        {
            this.textBoxExpenseHeadDefaultNarration.Enabled = this.checkBoxExpenseHeadDefaultNarration.Checked;
        }

        private void checkBoxExpenseHeadDefaultTransactionMode_CheckedChanged(object sender, EventArgs e)
        {
            this.comboBoxExpenseHeadDefaultTransactionMode.Enabled = this.checkBoxExpenseHeadDefaultTransactionMode.Checked;
        }

        private void checkBoxExpenseHeadDefaultBankAccount_CheckedChanged(object sender, EventArgs e)
        {
            this.comboBoxExpenseHeadDefaultBankAccount.Enabled = this.checkBoxExpenseHeadDefaultBankAccount.Checked;
        }

        private void ResetExpenseHeadDefaultValuesControls()
        {
            this.checkBoxExpenseHeadDefaultApprovers.Checked = false;
            this.radioButtonSetExpenseHeadApprovers.Enabled = this.checkBoxExpenseHeadDefaultApprovers.Checked;
            this.radioButtonSetExpenseHeadAutoApproval.Enabled = this.checkBoxExpenseHeadDefaultApprovers.Checked;
            this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.Enabled = this.radioButtonSetExpenseHeadApprovers.Enabled;
            this.checkBoxComboBoxSelectExpenseHeadDefaultApprovers.ClearSelection();

            this.checkBoxExpenseHeadDefaultAmount.Checked = false;
            this.textBoxExpenseHeadDefaultAmount.Enabled = this.checkBoxExpenseHeadDefaultAmount.Checked;
            this.textBoxExpenseHeadDefaultAmount.Clear();

            this.checkBoxExpenseHeadDefaultNarration.Checked = false;
            this.textBoxExpenseHeadDefaultNarration.Enabled = this.checkBoxExpenseHeadDefaultNarration.Checked;
            this.textBoxExpenseHeadDefaultNarration.Clear();

            this.checkBoxExpenseHeadDefaultTransactionMode.Checked = false;
            this.comboBoxExpenseHeadDefaultTransactionMode.Enabled = this.checkBoxExpenseHeadDefaultTransactionMode.Checked;

            this.checkBoxExpenseHeadDefaultBankAccount.Checked = false;
            this.comboBoxExpenseHeadDefaultBankAccount.Enabled = this.checkBoxExpenseHeadDefaultBankAccount.Checked;
        }

        #endregion Expense Head Default Values

        #region Transaction Type Sub Heads
        private void buttonAddSubHeads_Click(object sender, EventArgs e)
        {
            if (_formForSelectingParentForAddingChildren == null || _formForSelectingParentForAddingChildren.GetSelectedTransactionTypes().Count == 0 || _formForSelectingParentForAddingChildren.GetSelectedTransactionTypes().First().ParentId == -1)
            {
                MessageBox.Show("Please choose a valid head (other than the root) to add sub heads.", "Choose valid head", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            chosenParentTransactionTypeForAddingChildren = _formForSelectingParentForAddingChildren.GetSelectedTransactionTypes().Last();


            List<string> enteredSubHeadList = new List<string>();
            enteredSubHeadList.AddRange(this.richTextBoxSubHeads.Lines);
            enteredSubHeadList.RemoveAll(t => string.IsNullOrEmpty(t.Trim()));

            if (enteredSubHeadList.Count == 0)
            {
                MessageBox.Show("Please enter valid sub heads to add.", "Add sub heads", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            else
            {
                List<TransactionType> subHeadsToAdd = new List<TransactionType>();
                foreach (string subHead in enteredSubHeadList)
                {
                    TransactionType transactionType = new TransactionType();
                    transactionType.CreatedBy = LoginForm.LoggedInUserName;
                    transactionType.CreatedDate = DateTime.Now;
                    transactionType.IsActive = true;
                    transactionType.Name = subHead;
                    transactionType.ParentId = chosenParentTransactionTypeForAddingChildren.Id;
                    transactionType.UpdatedBy = LoginForm.LoggedInUserName;
                    transactionType.UpdatedDate = DateTime.Now;

                    subHeadsToAdd.Add(transactionType);
                }

                try
                {
                    this.dataAccessHandlerCommonInstance.SaveTransactionTypeList(subHeadsToAdd, MainForm.Context);
                    MessageBox.Show("Your data was saved sucessfully", "Save successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    this.richTextBoxSubHeads.Clear();
                    this.labelChosenParentHead.Text = string.Empty;
                    chosenParentTransactionTypeForAddingChildren = null;
                    PopulateParentSelectionForAddingChildren();
                }
                catch
                {
                    MessageBox.Show("There was a problem saving your data. \r\n Please view the log file and share it with your administrator.", "Save failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

            }
        }

        private void PopulateParentSelectionForAddingChildren()
        {
            _formForSelectingParentForAddingChildren = new TransactionTypeTreeViewForm(false, true, false);
            this.treeViewSelectParentNodeToAddChildren.Nodes.Clear();
            this.treeViewSelectParentNodeToAddChildren.CheckBoxes = false;
            _formForSelectingParentForAddingChildren.UseExternalTreeView(ref this.treeViewSelectParentNodeToAddChildren, ref this.labelChosenParentHead);
            _formForSelectingParentForAddingChildren.CreateTreeView(new List<string>(), true, true);
            this.treeViewSelectParentNodeToAddChildren.Refresh();
            this.treeViewSelectParentNodeToAddChildren.Visible = true;
        }
        #endregion Transaction Type Sub Heads

        #region App Settings
        private void PopulateApplicationSettings()
        {
            List<ApplicationSetting> applicationSettingList = SettingsAndStaticListLoader.ApplicationSettingList;

            this.textBoxVoucherPrefixValueAppSetting.Text = applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.VoucherPrefix)).FirstOrDefault().SettingValue;
            this.textBoxReceiptPrefixValueAppSetting.Text = applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.ReceiptPrefix)).FirstOrDefault().SettingValue;
            this.textBoxScannedImageLocationValueAppSetting.Text = applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.ScannedImageLocation)).FirstOrDefault().SettingValue;
            this.textBoxExportedFilesValueAppSetting.Text = applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.ExportedFilesLocation)).FirstOrDefault().SettingValue;
            this.textBoxVoucherReceiptLocationValueAppSetting.Text = applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.VoucherReceiptLocation)).FirstOrDefault().SettingValue;
            this.numericUpDownMaxDateRangeValueAppSetting.Value = int.Parse(applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.MaxDateRangeInDays)).FirstOrDefault().SettingValue);
            this.numericUpDownRowsPerPageValueAppSetting.Value = int.Parse(applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.RowsPerPage)).FirstOrDefault().SettingValue);

            int selectedIndex = 0;
            int index = 0;
            string currentDefaultExpenseBankAccount = applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.DefaultExpenseBankAccount)).FirstOrDefault().SettingValue;
            foreach (StaticList staticList in SettingsAndStaticListLoader.BankAccountsStaticList)
            {
                ComboBoxItem comboBoxItem = new ComboBoxItem(staticList.ListItemValue, staticList);
                this.comboBoxDefaultExpenseBankAccountValueAppSetting.Items.Add(comboBoxItem);
                if (staticList.ListItemCode.Equals(currentDefaultExpenseBankAccount))
                {
                    selectedIndex = index;
                }
                index++;
            }

            this.comboBoxDefaultExpenseBankAccountValueAppSetting.SelectedIndex = selectedIndex;

            selectedIndex = 0;
            index = 0;
            string currentDefaultIncomeBankAccount = applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.DefaultIncomeDepositBankAccount)).FirstOrDefault().SettingValue;
            foreach (StaticList staticList in SettingsAndStaticListLoader.BankAccountsStaticList)
            {
                ComboBoxItem comboBoxItem = new ComboBoxItem(staticList.ListItemValue, staticList);
                this.comboBoxDefaultIncomeBankAccountValueAppSetting.Items.Add(comboBoxItem);
                if (staticList.ListItemCode.Equals(currentDefaultIncomeBankAccount))
                {
                    selectedIndex = index;
                }
                index++;
            }

            this.comboBoxDefaultIncomeBankAccountValueAppSetting.SelectedIndex = selectedIndex;
        }

        private void buttonSaveAppSettings_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.textBoxExportedFilesValueAppSetting.Text.Trim()) ||
                string.IsNullOrEmpty(this.textBoxExportedFilesValueAppSetting.Text.Trim()) ||
                string.IsNullOrEmpty(this.textBoxVoucherReceiptLocationValueAppSetting.Text.Trim()) ||
                !Utils.HasWritePermissions(this.textBoxExportedFilesValueAppSetting.Text.Trim()) ||
                !Utils.HasWritePermissions(this.textBoxExportedFilesValueAppSetting.Text.Trim()) ||
                !Utils.HasWritePermissions(this.textBoxVoucherReceiptLocationValueAppSetting.Text.Trim()))
            {
                MessageBox.Show("Please ensure you select a proper location where users would have write permissions.", "Invalid location", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }


            List<ApplicationSetting> applicationSettingList = SettingsAndStaticListLoader.ApplicationSettingList;

            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.VoucherPrefix)).FirstOrDefault().SettingValue = this.textBoxVoucherPrefixValueAppSetting.Text.Trim();
            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.ReceiptPrefix)).FirstOrDefault().SettingValue = this.textBoxReceiptPrefixValueAppSetting.Text.Trim();
            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.ScannedImageLocation)).FirstOrDefault().SettingValue = this.textBoxScannedImageLocationValueAppSetting.Text.Trim();
            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.ExportedFilesLocation)).FirstOrDefault().SettingValue = this.textBoxExportedFilesValueAppSetting.Text.Trim();
            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.VoucherReceiptLocation)).FirstOrDefault().SettingValue = this.textBoxVoucherReceiptLocationValueAppSetting.Text.Trim();
            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.MaxDateRangeInDays)).FirstOrDefault().SettingValue = this.numericUpDownMaxDateRangeValueAppSetting.Value.ToString();
            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.RowsPerPage)).FirstOrDefault().SettingValue = this.numericUpDownRowsPerPageValueAppSetting.Value.ToString();

            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.DefaultExpenseBankAccount)).FirstOrDefault().SettingValue =
                ((StaticList)((ComboBoxItem)this.comboBoxDefaultExpenseBankAccountValueAppSetting.SelectedItem).Value).ListItemCode;

            applicationSettingList.Where(t => t.SettingName.Equals(Constants.AppSettingsKeys.DefaultIncomeDepositBankAccount)).FirstOrDefault().SettingValue =
                ((StaticList)((ComboBoxItem)this.comboBoxDefaultIncomeBankAccountValueAppSetting.SelectedItem).Value).ListItemCode;


            applicationSettingList.ForEach(t => { t.UpdatedBy = LoginForm.LoggedInUserName; t.UpdatedDate = DateTime.Now; });

            try
            {
                this.dataAccessHandlerCommonInstance.UpdateApplicationSettings(applicationSettingList, MainForm.Context);
                PopulateApplicationSettings();
                MessageBox.Show("Application settings were updated successfully.", "Update successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch
            {
                MessageBox.Show("Application settings were not saved. Pleas try againg or contact your administrator.", "Update failure", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
        
        private void buttonScannedImageLocation_Click(object sender, EventArgs e)
        {
            SetFolderLocation(this.textBoxScannedImageLocationValueAppSetting);
        }

        private void buttonExportedFilesLocation_Click(object sender, EventArgs e)
        {
            SetFolderLocation(this.textBoxExportedFilesValueAppSetting);
        }

        private void buttonVoucherReceiptLocation_Click(object sender, EventArgs e)
        {
            SetFolderLocation(this.textBoxVoucherReceiptLocationValueAppSetting);
        }

        private void SetFolderLocation(TextBox textBoxToSet)
        {
            this.folderBrowserDialogDefaultLocationSelector.ShowDialog();
            if(string.IsNullOrEmpty(this.folderBrowserDialogDefaultLocationSelector.SelectedPath))
            {
                MessageBox.Show("Please ensure you select a proper location where users would have write permissions.", "Invalid location", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            else if (!Utils.HasWritePermissions(this.folderBrowserDialogDefaultLocationSelector.SelectedPath))
            {
                MessageBox.Show("Either the folder does not exist or you do not have write permission on the selected folder. Please ensure you select a proper location where users would have write permissions.", "Invalid location", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            else
            {
                textBoxToSet.Text = this.folderBrowserDialogDefaultLocationSelector.SelectedPath;
            }
        }
        #endregion App Settings

        #endregion Private Methods

        #region Public Methods
        #endregion Public Methods
    }
}